/**
 * 
 */
package com.music.service.albums.dao.impl;


import static com.music.service.albums.constants.AlbumSQLQueries.ADD_EXISTING_ALBUM_TO_DEFAULT_FOLDER;
import static com.music.service.albums.constants.AlbumSQLQueries.ADD_NEW_ALBUM;
import static com.music.service.albums.constants.AlbumSQLQueries.ADD_SONG_TO_ALBUM;
import static com.music.service.albums.constants.AlbumSQLQueries.CHECK_ALBUM_PERMISSION;
import static com.music.service.albums.constants.AlbumSQLQueries.DELETE_ALBUM;
import static com.music.service.albums.constants.AlbumSQLQueries.DELETE_SONG_FROM_ALBUM;
import static com.music.service.albums.constants.AlbumSQLQueries.EDIT_ALBUM_NAME;
import static com.music.service.albums.constants.AlbumSQLQueries.VIEW_DEFAULT_ALBUMS;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Required;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

import com.music.service.albums.beans.Album;
import com.music.service.albums.constants.AlbumState;
import com.music.service.albums.dao.AlbumDAO;
import com.music.service.albums.exceptions.AlbumPermissionDeniedException;
import com.music.service.albums.mapper.AlbumMapper;
import com.music.service.folders.constants.FolderState;
import com.music.service.folders.mapper.CountMapper;


/**
 * @author asanthan
 *
 */
public class AlbumDAOImpl implements AlbumDAO {
	private JdbcTemplate mMusicsTemplate;

	
	
	/**
	 * @return the musicsTemplate
	 */
	public JdbcTemplate getMusicsTemplate() {
		return mMusicsTemplate;
	}

	/**
	 * @param pMusicsTemplate the musicsTemplate to set
	 */
	@Required
	public void setMusicsTemplate(JdbcTemplate pMusicsTemplate) {
		mMusicsTemplate = pMusicsTemplate;
	}

	@SuppressWarnings("unchecked")
	public List<Album> getDefaultAlbums(final Long pMemberId){
		List albums = getMusicsTemplate().query(VIEW_DEFAULT_ALBUMS,
				new PreparedStatementSetter() {
					public void setValues(PreparedStatement preparedStatement)
							throws SQLException {
						preparedStatement.setLong(1, pMemberId);
						preparedStatement.setInt(2, AlbumState.ACTIVE.getState());
					}
				}, new AlbumMapper());
		return albums;
	}
	
	public boolean addNewAlbumToDefaultFolder(final Long pMemberId, final String pAlbumName) {
		KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
		int nRowsUpdated = getMusicsTemplate().update(
				new PreparedStatementCreator() {
					public PreparedStatement createPreparedStatement(Connection conn)
							throws SQLException {
						PreparedStatement preparedStatement = conn.prepareStatement(ADD_NEW_ALBUM);
							preparedStatement.setLong(1, pMemberId);
						preparedStatement.setString(2, pAlbumName);
						preparedStatement.setInt(3, AlbumState.ACTIVE.getState());
						return preparedStatement;
					}
				},generatedKeyHolder);

		if(nRowsUpdated == 1){
			Long albumId = generatedKeyHolder.getKey().longValue();
			return addExistingAlbumToDefaultFolder(pMemberId, albumId);
		}else{
			return false;
		}
	}
	
	
	public boolean addExistingAlbumToDefaultFolder(final Long pMemberId, final Long pAlbumId) {
		int nRowsUpdated = getMusicsTemplate().update(ADD_EXISTING_ALBUM_TO_DEFAULT_FOLDER,
			new PreparedStatementSetter() {
				public void setValues(
						PreparedStatement preparedStatement)
						throws SQLException {
					preparedStatement.setLong(1, pMemberId);
					preparedStatement.setLong(2, pAlbumId);
					preparedStatement.setInt(3, FolderState.ACTIVE
							.getState());
				}
			});
		return nRowsUpdated == 1;
	}
	
	public boolean deleteAlbum(final Long pMemberId,final Long pAlbumId) {
		int nRowsUpdated = getMusicsTemplate().update(DELETE_ALBUM,
				new PreparedStatementSetter() {
					public void setValues(PreparedStatement preparedStatement)
							throws SQLException {
						preparedStatement.setInt(1, AlbumState.DELETED.getState());
						preparedStatement.setLong(2, pAlbumId);
						preparedStatement.setLong(3, pMemberId);
						preparedStatement.setInt(4, AlbumState.VERIFIED.getState());
					}
				});
		return nRowsUpdated == 1;
	}

	public boolean editAlbumName(final Long pMemberId, final Long pAlbumId,final String pAlbumName) {
		int nRowsUpdated = getMusicsTemplate().update(EDIT_ALBUM_NAME,
				new PreparedStatementSetter() {
					public void setValues(PreparedStatement preparedStatement)
							throws SQLException {
						preparedStatement.setString(1, pAlbumName);
						preparedStatement.setLong(2, pAlbumId);
						preparedStatement.setLong(2, pMemberId);
						preparedStatement.setInt(3, AlbumState.ACTIVE.getState());
					}
				});
		return nRowsUpdated == 1;
	}
	
	/**
	 * Note: Anyone can add any song to any album irrespective of album state.
	 * @param pMemberId
	 * @param pAlbumId
	 * @param pSongId
	 * @return
	 */
	public boolean addSongToAlbum(final Long pMemberId,final Long pAlbumId,final Long pSongId){
		
		int nRowsUpdated = getMusicsTemplate().update(ADD_SONG_TO_ALBUM,
					new PreparedStatementSetter() {
						public void setValues(PreparedStatement preparedStatement)
								throws SQLException {
							preparedStatement.setLong(1, pAlbumId);
							preparedStatement.setLong(2, pSongId);
							preparedStatement.setLong(3, pMemberId);
						}
					});
		return nRowsUpdated == 1;
		
	}
	
	/**
	 * Only owner of album can delete song.
	 * @param pMemberId
	 * @param pAlbumId
	 * @param pSongId
	 * @return
	 * @throws AlbumPermissionDeniedException
	 */
	public boolean deleteSongFromAlbum(final Long pMemberId,final Long pAlbumId,final Long pSongId) throws AlbumPermissionDeniedException{
		//if(checkMemberPermissionForAlbum(pMemberId, pAlbumId)){
		//if song state is not verfied,
			int nRowsUpdated = getMusicsTemplate().update(DELETE_SONG_FROM_ALBUM,
					new PreparedStatementSetter() {
						public void setValues(PreparedStatement preparedStatement)
								throws SQLException {
							preparedStatement.setLong(1, pAlbumId);
							preparedStatement.setLong(2, pSongId);
							preparedStatement.setLong(3, pMemberId);
						}
					});
			return nRowsUpdated == 1;
		/*}else{
			throw new AlbumPermissionDeniedException("You do not have privilege to delete song from album");
		}*/
		
	}
	@SuppressWarnings("unchecked")
	public boolean checkMemberPermissionForAlbum(final Long pMemberId,final Long pAlbumId) {
		List<Integer> counts = getMusicsTemplate().query(
				CHECK_ALBUM_PERMISSION, new PreparedStatementSetter() {
					public void setValues(PreparedStatement preparedStatement)
							throws SQLException {
						preparedStatement.setLong(1, pAlbumId);
						preparedStatement.setLong(2, pMemberId);
						preparedStatement.setInt(3, AlbumState.ACTIVE.getState());
					}
				}, new CountMapper());

		if (!counts.isEmpty()) {
			return counts.get(0) == 1;
		}
		return false;
	}

}
